From 60b6a010e931aaaf97d723c893068381a421f0a0 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 18 Apr 2001 18:09:18 +0000 Subject: [PATCH] fix to properly queue resizes when the image is set 2001-04-18 Havoc Pennington * gtk/gtkimage.c: fix to properly queue resizes when the image is set * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste if the insertion point isn't editable * demos/gtk-demo/images.c: Added a GtkImage demo * demos/gtk-demo/drawingarea.c: drawing area demo * demos/gtk-demo/menus.c (create_menu): cleanups 2001-04-18 Havoc Pennington * gdk-pixbuf.c (gdk_pixbuf_fill): Function to fill pixbuf with a given color. --- ChangeLog | 14 + ChangeLog.pre-2-0 | 14 + ChangeLog.pre-2-10 | 14 + ChangeLog.pre-2-2 | 14 + ChangeLog.pre-2-4 | 14 + ChangeLog.pre-2-6 | 14 + ChangeLog.pre-2-8 | 14 + demos/gtk-demo/Makefile.am | 22 +- demos/gtk-demo/apple-red.png | Bin 0 -> 3545 bytes demos/gtk-demo/background.jpg | Bin 0 -> 22219 bytes demos/gtk-demo/button_box.c | 20 +- demos/gtk-demo/drawingarea.c | 322 ++++++++++++++++++ demos/gtk-demo/gnome-applets.png | Bin 0 -> 3090 bytes demos/gtk-demo/gnome-calendar.png | Bin 0 -> 2755 bytes demos/gtk-demo/gnome-foot.png | Bin 0 -> 2916 bytes demos/gtk-demo/gnome-gimp.png | Bin 0 -> 3410 bytes demos/gtk-demo/gnome-gmush.png | Bin 0 -> 3244 bytes demos/gtk-demo/gnome-gsame.png | Bin 0 -> 4263 bytes demos/gtk-demo/gnu-keys.png | Bin 0 -> 3852 bytes demos/gtk-demo/gtk-logo-rgb.gif | Bin 0 -> 6459 bytes demos/gtk-demo/images.c | 396 +++++++++++++++++++++++ demos/gtk-demo/main.c | 31 +- demos/gtk-demo/menus.c | 34 +- demos/gtk-demo/pixbufs.c | 277 ++++++++++++++++ demos/pixbuf-demo.c | 4 +- docs/reference/gtk/tmpl/gtk-unused.sgml | 12 - docs/reference/gtk/tmpl/gtkrc.sgml | 1 + docs/reference/gtk/tmpl/gtktextview.sgml | 10 + gdk-pixbuf/ChangeLog | 5 + gdk-pixbuf/gdk-pixbuf.c | 58 ++++ gdk-pixbuf/gdk-pixbuf.h | 3 + gtk/gtkimage.c | 23 +- gtk/gtktextview.c | 11 +- 33 files changed, 1274 insertions(+), 53 deletions(-) create mode 100644 demos/gtk-demo/apple-red.png create mode 100644 demos/gtk-demo/background.jpg create mode 100644 demos/gtk-demo/drawingarea.c create mode 100644 demos/gtk-demo/gnome-applets.png create mode 100644 demos/gtk-demo/gnome-calendar.png create mode 100644 demos/gtk-demo/gnome-foot.png create mode 100644 demos/gtk-demo/gnome-gimp.png create mode 100644 demos/gtk-demo/gnome-gmush.png create mode 100644 demos/gtk-demo/gnome-gsame.png create mode 100644 demos/gtk-demo/gnu-keys.png create mode 100644 demos/gtk-demo/gtk-logo-rgb.gif create mode 100644 demos/gtk-demo/images.c create mode 100644 demos/gtk-demo/pixbufs.c diff --git a/ChangeLog b/ChangeLog index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am index 6fa87fac72..b581f51e14 100644 --- a/demos/gtk-demo/Makefile.am +++ b/demos/gtk-demo/Makefile.am @@ -2,12 +2,17 @@ democodedir=$(datadir)/gtk-2.0/demo +## These should be in the order you want them to appear in the +## demo app, which means alphabetized by demo title, not filename demos = @STRIP_BEGIN@ \ button_box.c \ + dialog.c \ + drawingarea.c \ + images.c \ item_factory.c \ menus.c \ panes.c \ - dialog.c \ + pixbufs.c \ textview.c \ @STRIP_END@ @@ -63,4 +68,17 @@ gtk_demo_SOURCES = \ gtk_demo_DEPENDENCIES = $(DEPS) gtk_demo_LDADD = $(LDADDS) -democode_DATA = $(demos) +IMAGEFILES= apple-red.png \ + background.jpg \ + gnome-applets.png \ + gnome-calendar.png \ + gnome-foot.png \ + gnome-gimp.png \ + gnome-gmush.png \ + gnome-gsame.png \ + gnu-keys.png \ + gtk-logo-rgb.gif + +democode_DATA = $(demos) $(IMAGEFILES) + +EXTRA_DIST = $(IMAGEFILES) diff --git a/demos/gtk-demo/apple-red.png b/demos/gtk-demo/apple-red.png new file mode 100644 index 0000000000000000000000000000000000000000..b0a24e941859564debfe60122d4fb60ab32cacab GIT binary patch literal 3545 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 T!37SN00000NkvXXu0mjf{xHB+ literal 0 HcmV?d00001 diff --git a/demos/gtk-demo/background.jpg b/demos/gtk-demo/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86c006aa466a0c5875a39087c9765b6eb79433be GIT binary patch literal 22219 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 z zCR0R9CKYtz+E*Hn;Kf}L-$)9e08Lr5QtltwOZ$aM=X4*=616k4iM{Cc@?_b5?t8SAZ_Q zk~glf4L}5y)aFqnCIk}yHDmlw1^+iHp!!Kcn}s8*@EwelLyg8^cqqBw=k`*b1)fBb zT#f#wr_OizB~CRoJRR6KV0z z$tkl#<7_L%-9Nu?7IQkfYtQRosp`nItgQZ5pQSA z$d;Lk8?~o@(w~;M=~E;H25C^6mgb=>$O@^{z9u(eb1Ff?c{vBh`oye_{aX3#ezF>L z0wVUx#DnHHniX;-K+MMvb{E8$8|6`&5vtNJB-K?qu0Y=T;gSSdpvg0su(@p_nj5KQ z)A8rE+UiN&1)J!{XmFIL#~u8uHR1eD$V>l5ay}We6@VoaTpVZh#QZ=i@GgN+vQ!=h z0x`j}(qVVb0QIsRAMB&$ABwlisC@5v;Bi$pe$)<3q4|z$O&xN+X}AR{j67MM+VYqA zL^q(U8=kau~D|3y|4TSu{I`Who3jg`sT1v^S)0{{5QuCr4di&0znQG3f>l>0r2 zKZts39r8ghIG-i))){cHP}x}w&a$Fb82#$!BfBUM=)SY>`0yq;EUB~)GrQ1X|2#6? zW&JgVCGEWTB&{|tM=N?c2>0%Ns3e#46XZn$p9f?#~Msr7*qvQ38l%Vhu__Fb&;=Snhdmv%Ya=KJs3&pQmd6%k=ih7Fv%cT z2s!ep4dd3sy_L$>??&2nDAw`uPb45X2wuhW%E^nK+*qH;XlsiI`(8-e)W4QH zo^*`Po>&W3#USM<#GQT+pj=z&{V zr^8Lf4f>_CmOL|A0>awF<7NPHA64=1jXJ`T&e@tLB_saM-j;WX^un^AV--A%PkZpg zm(=yN$|m0sm((b5HSle_)3Fgd6QNZ5?NF0zs4_ z8mg1;sx9glrl?Wsp4}XW*j!9AqdZ!iZF; zav(#C*)^F1g>w~y&wG1}p`(olNZZ?xoPs)A%l>vYh0T^>0{RE5FpWDBtJ&k8T9j7X z@m=m%aOK&X%KSl#Li8WoOkdcMnNYf zpwZzIzHyWkUp7~2i42_(OmHB8NNKDji`!DS6U~R$bf$Y~6GaB{^n#!7HXD6Euy*q2 z-8YkJv;tGJ1(36e!sI_v7@bl8pSnTJU zyJtZ4N2@Y1{P|Y;?q$AacgmjLT-?`43axBRd3^`GclVU{^@XbrX+Q!S%66Z5Y`u3U8YtW!+Aw=$^6Z> z9_>w@s7m34#L?Ig2{;?)@qb0lBJr#J-csmfDXZd2L>{ej!jS{`#bRJZ1<~si~g# z=LqvLj>c{DaINjNv|kf60BW1AuZw1PV^^*+%JfP5u~LwD|6x&Xb+Xy`)flPx_i~d z^>P0Yuzv{HKLqR_0`?C9`-g!2L%{waVE+)Xe+bw=1neII_74I3hk*S>mR54*~m!fc->mR54*~m!fc- + +static GtkWidget *window = NULL; +/* Pixmap for scribble area, to store current scribbles */ +static GdkPixmap *pixmap = NULL; + +/* Create a new pixmap of the appropriate size to store our scribbles */ +static gboolean +scribble_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer data) +{ + if (pixmap) + g_object_unref (G_OBJECT (pixmap)); + + pixmap = gdk_pixmap_new (widget->window, + widget->allocation.width, + widget->allocation.height, + -1); + + /* Initialize the pixmap to white */ + gdk_draw_rectangle (pixmap, + widget->style->white_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + /* We've handled the configure event, no need for further processing. */ + return TRUE; +} + +/* Redraw the screen from the pixmap */ +static gboolean +scribble_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + /* We use the "foreground GC" for the widget since it already exists, + * but honestly any GC would work. The only thing to worry about + * is whether the GC has an inappropriate clip region set. + */ + + gdk_draw_drawable (widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + pixmap, + /* Only copy the area that was exposed. */ + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +/* Draw a rectangle on the screen */ +static void +draw_brush (GtkWidget *widget, + gdouble x, + gdouble y) +{ + GdkRectangle update_rect; + + update_rect.x = x - 3; + update_rect.y = y - 3; + update_rect.width = 6; + update_rect.height = 6; + + /* Paint to the pixmap, where we store our state */ + gdk_draw_rectangle (pixmap, + widget->style->black_gc, + TRUE, + update_rect.x, update_rect.y, + update_rect.width, update_rect.height); + + /* Now invalidate the affected region of the drawing area. */ + gdk_window_invalidate_rect (widget->window, + &update_rect, + FALSE); +} + +static gboolean +scribble_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + if (pixmap == NULL) + return FALSE; /* paranoia check, in case we haven't gotten a configure event */ + + if (event->button == 1) + draw_brush (widget, event->x, event->y); + + /* We've handled the event, stop processing */ + return TRUE; +} + +static gboolean +scribble_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer data) +{ + int x, y; + GdkModifierType state; + + if (pixmap == NULL) + return FALSE; /* paranoia check, in case we haven't gotten a configure event */ + + /* This call is very important; it requests the next motion event. + * If you don't call gdk_window_get_pointer() you'll only get + * a single motion event. The reason is that we specified + * GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events(). + * If we hadn't specified that, we could just use event->x, event->y + * as the pointer location. But we'd also get deluged in events. + * By requesting the next event as we handle the current one, + * we avoid getting a huge number of events faster than we + * can cope. + */ + + gdk_window_get_pointer (event->window, &x, &y, &state); + + if (state & GDK_BUTTON1_MASK) + draw_brush (widget, x, y); + + /* We've handled it, stop processing */ + return TRUE; +} + + +static gboolean +checkerboard_expose (GtkWidget *da, + GdkEventExpose *event, + gpointer data) +{ + gint i, j, xcount, ycount; + GdkGC *gc1, *gc2; + GdkColor color; + +#define CHECK_SIZE 10 +#define SPACING 2 + + /* At the start of an expose handler, a clip region of event->area + * is set on the window, and event->area has been cleared to the + * widget's background color. The docs for + * gdk_window_begin_paint_region() give more details on how this + * works. + */ + + /* It would be a bit more efficient to keep these + * GC's around instead of recreating on each expose, but + * this is the lazy/slow way. + */ + gc1 = gdk_gc_new (da->window); + color.red = 30000; + color.green = 0; + color.blue = 30000; + gdk_gc_set_rgb_fg_color (gc1, &color); + + gc2 = gdk_gc_new (da->window); + color.red = 65535; + color.green = 65535; + color.blue = 65535; + gdk_gc_set_rgb_fg_color (gc2, &color); + + xcount = 0; + i = SPACING; + while (i < da->allocation.width) + { + j = SPACING; + ycount = xcount % 2; /* start with even/odd depending on row */ + while (j < da->allocation.height) + { + GdkGC *gc; + + if (ycount % 2) + gc = gc1; + else + gc = gc2; + + /* If we're outside event->area, this will do nothing. + * It might be mildly more efficient if we handled + * the clipping ourselves, but again we're feeling lazy. + */ + gdk_draw_rectangle (da->window, + gc, + TRUE, + i, j, + CHECK_SIZE, + CHECK_SIZE); + + j += CHECK_SIZE + SPACING; + ++ycount; + } + + i += CHECK_SIZE + SPACING; + ++xcount; + } + + g_object_unref (G_OBJECT (gc1)); + g_object_unref (G_OBJECT (gc2)); + + /* return TRUE because we've handled this event, so no + * further processing is required. + */ + return TRUE; +} + +GtkWidget * +do_drawingarea (void) +{ + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *da; + GtkWidget *label; + + if (!window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Drawing Area"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + + gtk_container_set_border_width (GTK_CONTAINER (window), 8); + + vbox = gtk_vbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); + gtk_container_add (GTK_CONTAINER (window), vbox); + + /* + * Create the checkerboard area + */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "Checkerboard pattern"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); + + da = gtk_drawing_area_new (); + /* set a minimum size */ + gtk_widget_set_usize (da, 100, 100); + + gtk_container_add (GTK_CONTAINER (frame), da); + + gtk_signal_connect (GTK_OBJECT (da), + "expose_event", + GTK_SIGNAL_FUNC (checkerboard_expose), + NULL); + + /* + * Create the scribble area + */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "Scribble area"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); + + da = gtk_drawing_area_new (); + /* set a minimum size */ + gtk_widget_set_usize (da, 100, 100); + + gtk_container_add (GTK_CONTAINER (frame), da); + + /* Signals used to handle backing pixmap */ + + gtk_signal_connect (GTK_OBJECT (da), "expose_event", + GTK_SIGNAL_FUNC (scribble_expose_event), NULL); + gtk_signal_connect (GTK_OBJECT (da),"configure_event", + GTK_SIGNAL_FUNC (scribble_configure_event), NULL); + + /* Event signals */ + + gtk_signal_connect (GTK_OBJECT (da), "motion_notify_event", + GTK_SIGNAL_FUNC (scribble_motion_notify_event), NULL); + gtk_signal_connect (GTK_OBJECT (da), "button_press_event", + GTK_SIGNAL_FUNC (scribble_button_press_event), NULL); + + + /* Ask to receive events the drawing area doesn't normally + * subscribe to + */ + gtk_widget_set_events (da, gtk_widget_get_events (da) + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/gtk-demo/gnome-applets.png b/demos/gtk-demo/gnome-applets.png new file mode 100644 index 0000000000000000000000000000000000000000..8d3549e97c0898e6bb22bf67d87c7165df8cf3e5 GIT binary patch literal 3090 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 literal 0 HcmV?d00001 diff --git a/demos/gtk-demo/gnome-calendar.png b/demos/gtk-demo/gnome-calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..889f329ae5febbc3980ebeb945939f22368d7aab GIT binary patch literal 2755 zcmV;!3Ox0RP)LD)9$o8?N0lDZsHSelm4Ut z5VtU>6Fc<(5`gHyc)iJe;s%E68-cJtCc{Ms4%*Cku?dCr%|LVn;CJ8orcz3ywIWm@ z^*~Wq3WY!j3t;wtRLi=_6S`FX#36w%;vFJk-4|u#xa1t z`rKjRg^JbG7Lm$r<8y}&b(truSicPbVMw4td=+x{*Po+MD3D5}C|)U2uhfxJw!9y- zfB@73)$;n9M3zdFPM$>0ml|FN}Ba7pd#>O|$DRKnB za1ikL7rrE3Jbak`?(T<-@m;_cARXD>Q4aV@p_C$%%y4<~GL@AI?y5_zR-<06Z}7Mb zB#!OG%7}&loCgo!1Pw!-2O9S~Q6AWkd;CeH)5xW6&tr@0GJX6wpV`{2fAr2fzW{Ou zfCiRg zWPw#+&QM5q6oEj6gsL%;V>=DvIi})79yKFPoS8r_eL(L1JV%cnWj` zPXy2Wj0X=r*r1WqqL~aNp66lD&!Z}3RNm@Q_^fEv z!w{v6(Xo;lc`aVkckkQHgp?GgC9gmB7}E0a#AThB%XpjIQi zZ~@PCab1^6p@3YT7wewXz)r)mW#fG}deZ7Z8VEm71WGlNGpZQzr7D&q~o|L$Yi(CjnQ_p`(^lS<6J)gqZgK?dJl4KyT1E1T?7-2h-cz z%ie*#tgWr#q|;b6pXKFc*6bllEd}bpwr$&}t2#aB&r_|}xq9^~ z%2Mpyy_0-k;hsIqbSg!8VS%}o70v?L?kvMY!we1#66gRS1X`nw35l53ZIIZ(|?{?UI&u+T9x=1B$_T9gagP%Rf$j}h=i|2Xx)mN!|9!svvL=a+a z=_bD;&%nR{=~NmK`CW@RAFNmsTQ|#r>!P5AMr*WVJEEcEBu=-}C~86DH$X0%Yep%P z%wXF#N!w=c&|Y%691AD@O5gA>$KQB^U5`A%NA3zUSFY0E+smFkd&uQ-SXRrY3DNYY zXak{dHWTaiWY$`v^u`^ANQ_A-H%JTu1H_b9tu>iUhSk{_db3&PM@N}HcaAe-V;ryh zWV2a@b`3E&Fi5&9O>Mo_qJlug>`|NTPIM9hrL`7;Qhe{3C-ulfkKFEFlKAP5U*YLP z50UThXL@v$CD&zCYnH>1tev1*t1>k^g*CsC(Tz!12&03-*scVfXrU(iltQojigMlO z#Jk6I+gpfgMU%Q(5Nd^EC%CK2VQVVQuHj)ZdFm8PuFF()U4K;d@B^Q)y2d4MovHD& zfNpFYC|2@&xi@_yL1y>deU5yv#3gt*CMCxpg?Iu>ss1Uh>A=SS{irC4P0!UZO) z>w3aTlk|NO2_e#{q_z{5Xe-|WwAL;9N4hs23EfEqG{9T$9?t?jzz$&09JiXqwGAXq zsk38c&IhVr+`oVOo+n1W{n2~xF+MkU`Ilp3?*iL^Uh|%^5o?|?E?Tf$1D4FvF)-uB zfv8SaWZK*q0PAMJx;b_MDPw$ejJ7=zkpqrA`sfQYV`EIt%#@B5i@!1BMG`qQ5_#GP zwJ-v1dc^>f=6XE_M0FB@_?!@xhdQtpGd${1BqAWzQwI;;SD%|3zBD_#^84}e9~Rfv zYG!#DnlUQCq*0oYSo34uGw+i$i+0QS+lfHbYB4WGhQ^~{$ADO085ucTDVO=%l`F50 zmr66n_%1W%s?qo}z=|0&qJ|%%P2IdV>bFfH(FP=F1E*pyv*UfeQkfr{nfb$CCMQn< z+s(SxGM-%ouEun}YD>~~5OMnGmQL$z%Y4Hk-}FRGqu8!JZ56%AxsJWaGJ{3{YHh-+E0(mYrU1+v&sU9c?K5pWvhC;k zwzt>Y^oNSQu>GTiwMo=;tfG`md0a5pR9lY4o7!YcUH!LTXmnd%w0{~3Z}64IjZtC6 zP)Ob6)6>n4ANx15_A#wkc@0c5>RWvD(|p33Xj{+T>cd{g?LQ#Ip01hj#P$FH002ov JPDHLkV1jV$NvHq- literal 0 HcmV?d00001 diff --git a/demos/gtk-demo/gnome-foot.png b/demos/gtk-demo/gnome-foot.png new file mode 100644 index 0000000000000000000000000000000000000000..04766585175baf1d68a0f1584dc31c1abd3315b8 GIT binary patch literal 2916 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 literal 0 HcmV?d00001 diff --git a/demos/gtk-demo/gnome-gsame.png b/demos/gtk-demo/gnome-gsame.png new file mode 100644 index 0000000000000000000000000000000000000000..01c061151f69e9e80cdcc29f4190f50dce809fca GIT binary patch literal 4263 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 JPDHLkV1n+!DZT&z literal 0 HcmV?d00001 diff --git a/demos/gtk-demo/gnu-keys.png b/demos/gtk-demo/gnu-keys.png new file mode 100644 index 0000000000000000000000000000000000000000..58a33770e67e60817ddbd85faeee8534d6f896fe GIT binary patch literal 3852 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 O0000nbV9Jy&js2p?TsCduZ3L{G8T_dDY?~#g* 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 +#include +#include + +static GtkWidget *window = NULL; +static GdkPixbufLoader *pixbuf_loader = NULL; +static guint load_timeout = 0; +static FILE* image_stream = NULL; + +static void +progressive_prepared_callback (GdkPixbufLoader* loader, gpointer data) +{ + GdkPixbuf* pixbuf; + GtkWidget* image; + + image = GTK_WIDGET (data); + + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + + /* Avoid displaying random memory contents, since the pixbuf + * isn't filled in yet. + */ + gdk_pixbuf_fill (pixbuf, 0xaaaaaaff); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); +} + +static void +progressive_updated_callback (GdkPixbufLoader* loader, + guint x, guint y, guint width, guint height, + gpointer data) +{ + GtkWidget* image; + + image = GTK_WIDGET (data); + + /* We know the pixbuf inside the image has changed, but the image + * itself doesn't know this; so queue a redraw. If we wanted to be + * really efficient, we could use a drawing area or something + * instead of a GtkImage, so we could control the exact position of + * the pixbuf on the display, then we could queue a draw for only + * the updated area of the image. + */ + + gtk_widget_queue_draw (image); +} + +static gint +progressive_timeout (gpointer data) +{ + GtkWidget *image; + + image = GTK_WIDGET (data); + + /* This shows off fully-paranoid error handling, so looks scary. + * You could factor out the error handling code into a nice separate + * function to make things nicer. + */ + + if (image_stream) + { + size_t bytes_read; + guchar buf[256]; + GError *error = NULL; + + bytes_read = fread (buf, 1, 256, image_stream); + + if (ferror (image_stream)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failure reading image file 'gtk-logo-rgb.gif': %s", + g_strerror (errno)); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + fclose (image_stream); + image_stream = NULL; + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (!gdk_pixbuf_loader_write (pixbuf_loader, + buf, bytes_read, + &error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + fclose (image_stream); + image_stream = NULL; + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (feof (image_stream)) + { + fclose (image_stream); + image_stream = NULL; + + /* Errors can happen on close, e.g. if the image + * file was truncated we'll know on close that + * it was incomplete. + */ + error = NULL; + if (!gdk_pixbuf_loader_close (pixbuf_loader, + &error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + } + else + { + const gchar *filename; + + if (g_file_test ("./gtk-logo-rgb.gif", G_FILE_TEST_EXISTS)) + filename = "./gtk-logo-rgb.gif"; + else + filename = DEMOCODEDIR"/gtk-log-rgb.gif"; + + image_stream = fopen (filename, "r"); + + if (image_stream == NULL) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to open image file 'gtk-logo-rgb.gif': %s", + g_strerror (errno)); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (pixbuf_loader) + { + gdk_pixbuf_loader_close (pixbuf_loader, NULL); + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + + pixbuf_loader = gdk_pixbuf_loader_new (); + + g_signal_connect_data (G_OBJECT (pixbuf_loader), + "area_prepared", + G_CALLBACK (progressive_prepared_callback), + image, + NULL, FALSE, FALSE); + + g_signal_connect_data (G_OBJECT (pixbuf_loader), + "area_updated", + G_CALLBACK (progressive_updated_callback), + image, + NULL, FALSE, FALSE); + } + + /* leave timeout installed */ + return TRUE; +} + +static void +start_progressive_loading (GtkWidget *image) +{ + /* This is obviously totally contrived (we slow down loading + * on purpose to show how incremental loading works). + * The real purpose of incremental loading is the case where + * you are reading data from a slow source such as the network. + * The timeout simply simulates a slow data source by inserting + * pauses in the reading process. + */ + load_timeout = g_timeout_add (300, + progressive_timeout, + image); +} + +static void +cleanup_callback (GtkObject *object, + gpointer data) +{ + if (load_timeout) + { + g_source_remove (load_timeout); + load_timeout = 0; + } + + if (pixbuf_loader) + { + gdk_pixbuf_loader_close (pixbuf_loader, NULL); + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + + if (image_stream) + fclose (image_stream); + image_stream = NULL; +} + +GtkWidget * +do_images (void) +{ + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *image; + GtkWidget *label; + GtkWidget *align; + + if (!window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Images"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (cleanup_callback), NULL); + + gtk_container_set_border_width (GTK_CONTAINER (window), 8); + + vbox = gtk_vbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "Image loaded from a file"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + /* The alignment keeps the frame from growing when users resize + * the window + */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (align), frame); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + /* We look for the image in the current directory first, + * so you can run gtk-demo without installing GTK + */ + if (g_file_test ("./gtk-logo-rgb.gif", G_FILE_TEST_EXISTS)) + { + /* This code shows off error handling. You can just use + * gtk_image_new_from_file() instead if you don't want to report + * errors to the user. If the file doesn't load when using + * gtk_image_new_from_file(), a "missing image" icon will + * be displayed instead. + */ + GdkPixbuf *pixbuf; + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file ("./gtk-logo-rgb.gif", + &error); + if (error) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to open image file 'gtk-logo-rgb.gif': %s", + error->message); + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + } + + image = gtk_image_new_from_pixbuf (pixbuf); + } + else + { + /* This is the simpler code, with no error handling. + * Here we're loading the installed gtk-logo-rgb.gif instead + * of the one in the current directory. + */ + image = gtk_image_new_from_file (DEMOCODEDIR"/gtk-logo-rgb.gif"); + } + + gtk_container_add (GTK_CONTAINER (frame), image); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "Progressive image loading"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + /* The alignment keeps the frame from growing when users resize + * the window + */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (align), frame); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + /* Create an empty image for now; the progressive loader + * will create the pixbuf and fill it in. + */ + image = gtk_image_new_from_pixbuf (NULL); + gtk_container_add (GTK_CONTAINER (frame), image); + + start_progressive_loading (image); + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index 0dfb4b1e26..fabf898d44 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -299,16 +299,18 @@ button_press_event_cb (GtkTreeView *tree_view, return FALSE; } -gboolean +void row_activated_cb (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - GtkTreeModel *model) + GtkTreePath *path, + GtkTreeViewColumn *column) { GtkTreeIter iter; gboolean italic; GDoDemoFunc func; GtkWidget *window; + GtkTreeModel *model; + + model = gtk_tree_view_get_model (tree_view); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (GTK_TREE_MODEL (model), @@ -321,6 +323,7 @@ row_activated_cb (GtkTreeView *tree_view, ITALIC_COLUMN, !italic, -1); window = (func) (); + if (window != NULL) { CallbackData *cbdata; @@ -334,10 +337,6 @@ row_activated_cb (GtkTreeView *tree_view, window_closed_cb, cbdata); } - else - { - gtk_tree_path_free (path); - } } static void @@ -385,9 +384,20 @@ create_text (GtkTextBuffer **buffer, font_desc = pango_font_description_from_string ("Courier 10"); gtk_widget_modify_font (text_view, font_desc); pango_font_description_free (font_desc); + + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), + GTK_WRAP_NONE); + } + else + { + /* Make it a bit nicer for text. */ + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), + GTK_WRAP_WORD); + gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (text_view), + 2); + gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (text_view), + 2); } - - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), !is_source); return scrolled_window; } @@ -458,6 +468,7 @@ main (int argc, char **argv) gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "GTK+ Code Demos"); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_main_quit), NULL); diff --git a/demos/gtk-demo/menus.c b/demos/gtk-demo/menus.c index ac8a7e2c53..4788edd861 100644 --- a/demos/gtk-demo/menus.c +++ b/demos/gtk-demo/menus.c @@ -1,10 +1,31 @@ /* Menus * - * GTK+ includes a number of widgets for menus of actions. - * GtkMenu is a drop-down menu, GtkMenuBar a horizontal menu bar. - * Each of these widgets can hold various types of menuitem. - * As well as the base type, GtkMenuItem, there are GtkCheckMenuItem, - * GtkRadioMenuItem and GtkTearoffMenuItem. + * There are several widgets involved in displaying menus. The + * GtkMenuBar widget is a horizontal menu bar, which normally appears + * at the top of an application. The GtkMenu widget is the actual menu + * that pops up. Both GtkMenuBar and GtkMenu are subclasses of + * GtkMenuShell; a GtkMenuShell contains menu items + * (GtkMenuItem). Each menu item contains text and/or images and can + * be selected by the user. + * + * There are several kinds of menu item, including plain GtkMenuItem, + * GtkCheckMenuItem which can be checked/unchecked, GtkRadioMenuItem + * which is a check menu item that's in a mutually exclusive group, + * GtkSeparatorMenuItem which is a separator bar, GtkTearoffMenuItem + * which allows a GtkMenu to be torn off, and GtkImageMenuItem which + * can place a GtkImage or other widget next to the menu text. + * + * A GtkMenuItem can have a submenu, which is simply a GtkMenu to pop + * up when the menu item is selected. Typically, all menu items in a menu bar + * have submenus. + * + * The GtkOptionMenu widget is a button that pops up a GtkMenu when clicked. + * It's used inside dialogs and such. + * + * GtkItemFactory provides a higher-level interface for creating menu bars + * and menus; while you can construct menus manually, most people don't + * do that. There's a separate demo for GtkItemFactory. + * */ #include @@ -39,8 +60,7 @@ create_menu (gint depth, gboolean tearoff) sprintf (buf, "item %2d - %d", depth, j); menuitem = gtk_radio_menu_item_new_with_label (group, buf); group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - if (depth % 2) - gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menuitem), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show (menuitem); if (i == 3) diff --git a/demos/gtk-demo/pixbufs.c b/demos/gtk-demo/pixbufs.c new file mode 100644 index 0000000000..6c067098ac --- /dev/null +++ b/demos/gtk-demo/pixbufs.c @@ -0,0 +1,277 @@ +/* Pixbufs + * + * A GdkPixbuf represents an image, normally in RGB or RGBA format. + * Pixbufs are normally used to load files from disk and perform + * image scaling. + * + * This demo is not all that educational, but looks cool. It was written + * by Extreme Pixbuf Hacker Federico Mena Quintero. It also shows + * off how to use GtkDrawingArea to do a simple animation. + * + * Look at the Image demo for additional pixbuf usage examples. + * + */ + +#include +#include +#include +#include + + + +#define FRAME_DELAY 50 + +#define RELATIVE_BACKGROUND_NAME "background.jpg" +#define INSTALLED_BACKGROUND_NAME DEMOCODEDIR"/background.jpg" + +static const char *relative_image_names[] = { + "apple-red.png", + "gnome-applets.png", + "gnome-calendar.png", + "gnome-foot.png", + "gnome-gmush.png", + "gnome-gimp.png", + "gnome-gsame.png", + "gnu-keys.png" +}; + +static const char *installed_image_names[] = { + DEMOCODEDIR"/apple-red.png", + DEMOCODEDIR"/gnome-applets.png", + DEMOCODEDIR"/gnome-calendar.png", + DEMOCODEDIR"/gnome-foot.png", + DEMOCODEDIR"/gnome-gmush.png", + DEMOCODEDIR"/gnome-gimp.png", + DEMOCODEDIR"/gnome-gsame.png", + DEMOCODEDIR"/gnu-keys.png" +}; + +#define N_IMAGES G_N_ELEMENTS (relative_image_names) + +/* demo window */ +static GtkWindow *window = NULL; + +/* Current frame */ +static GdkPixbuf *frame; + +/* Background image */ +static GdkPixbuf *background; +static int back_width, back_height; + +/* Images */ +static GdkPixbuf *images[N_IMAGES]; + +/* Widgets */ +static GtkWidget *da; + + + +/* Loads the images for the demo and returns whether the operation succeeded */ +static gboolean +load_pixbufs (GError **error) +{ + int i; + const char **image_names; + + if (background) + return TRUE; /* already loaded earlier */ + + background = gdk_pixbuf_new_from_file (RELATIVE_BACKGROUND_NAME, NULL); + + if (!background) + background = gdk_pixbuf_new_from_file (INSTALLED_BACKGROUND_NAME, error); + + if (!background) + return FALSE; /* note that "error" was filled in and returned */ + + back_width = gdk_pixbuf_get_width (background); + back_height = gdk_pixbuf_get_height (background); + + if (g_file_test (relative_image_names[0], G_FILE_TEST_EXISTS)) + image_names = relative_image_names; + else + image_names = installed_image_names; + + for (i = 0; i < N_IMAGES; i++) + { + images[i] = gdk_pixbuf_new_from_file (image_names[i], error); + if (!images[i]) + return FALSE; /* Note that "error" was filled with a GError */ + } + + return TRUE; +} + +/* Expose callback for the drawing area */ +static gint +expose_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + guchar *pixels; + int rowstride; + + rowstride = gdk_pixbuf_get_rowstride (frame); + + pixels = gdk_pixbuf_get_pixels (frame) + rowstride * event->area.y + event->area.x * 3; + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + event->area.x, event->area.y, + event->area.width, event->area.height, + GDK_RGB_DITHER_NORMAL, + pixels, rowstride, + event->area.x, event->area.y); + + return TRUE; +} + +#define CYCLE_LEN 60 + +static int frame_num; + +/* Timeout handler to regenerate the frame */ +static gint +timeout (gpointer data) +{ + double f; + int i; + double xmid, ymid; + double radius; + + gdk_pixbuf_copy_area (background, 0, 0, back_width, back_height, + frame, 0, 0); + + f = (double) (frame_num % CYCLE_LEN) / CYCLE_LEN; + + xmid = back_width / 2.0; + ymid = back_height / 2.0; + + radius = MIN (xmid, ymid) / 2.0; + + for (i = 0; i < N_IMAGES; i++) + { + double ang; + int xpos, ypos; + int iw, ih; + double r; + GdkRectangle r1, r2, dest; + double k; + + ang = 2.0 * M_PI * (double) i / N_IMAGES - f * 2.0 * M_PI; + + iw = gdk_pixbuf_get_width (images[i]); + ih = gdk_pixbuf_get_height (images[i]); + + r = radius + (radius / 3.0) * sin (f * 2.0 * M_PI); + + xpos = floor (xmid + r * cos (ang) - iw / 2.0 + 0.5); + ypos = floor (ymid + r * sin (ang) - ih / 2.0 + 0.5); + + k = (i & 1) ? sin (f * 2.0 * M_PI) : cos (f * 2.0 * M_PI); + k = 2.0 * k * k; + k = MAX (0.25, k); + + r1.x = xpos; + r1.y = ypos; + r1.width = iw * k; + r1.height = ih * k; + + r2.x = 0; + r2.y = 0; + r2.width = back_width; + r2.height = back_height; + + if (gdk_rectangle_intersect (&r1, &r2, &dest)) + gdk_pixbuf_composite (images[i], + frame, + dest.x, dest.y, + dest.width, dest.height, + xpos, ypos, + k, k, + GDK_INTERP_NEAREST, + ((i & 1) + ? MAX (127, fabs (255 * sin (f * 2.0 * M_PI))) + : MAX (127, fabs (255 * cos (f * 2.0 * M_PI))))); + } + + gtk_widget_queue_draw (da); + + frame_num++; + return TRUE; +} + +static guint timeout_id; + +static void +cleanup_callback (GtkObject *object, + gpointer data) +{ + g_source_remove (timeout_id); + timeout_id = 0; +} + +GtkWidget * +do_pixbufs (void) +{ + if (!window) + { + GError *error; + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Pixbufs"); + gtk_window_set_resizeable (GTK_WINDOW (window), FALSE); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (cleanup_callback), NULL); + + + error = NULL; + if (!load_pixbufs (&error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load an image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + } + else + { + gtk_widget_set_usize (window, back_width, back_height); + + frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, back_width, back_height); + + da = gtk_drawing_area_new (); + + gtk_signal_connect (GTK_OBJECT (da), "expose_event", + GTK_SIGNAL_FUNC (expose_cb), NULL); + + gtk_container_add (GTK_CONTAINER (window), da); + + timeout_id = gtk_timeout_add (FRAME_DELAY, timeout, NULL); + } + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/pixbuf-demo.c b/demos/pixbuf-demo.c index 0ee8aca460..641bdf3468 100644 --- a/demos/pixbuf-demo.c +++ b/demos/pixbuf-demo.c @@ -49,13 +49,13 @@ static GdkPixbuf *frame; /* Background image */ static GdkPixbuf *background; -int back_width, back_height; +static int back_width, back_height; /* Images */ static GdkPixbuf *images[N_IMAGES]; /* Widgets */ -GtkWidget *da; +static GtkWidget *da; diff --git a/docs/reference/gtk/tmpl/gtk-unused.sgml b/docs/reference/gtk/tmpl/gtk-unused.sgml index 84d2e992e1..c3ee353dcb 100644 --- a/docs/reference/gtk/tmpl/gtk-unused.sgml +++ b/docs/reference/gtk/tmpl/gtk-unused.sgml @@ -723,18 +723,6 @@ produce superscript and subscript. - - - - - - - - - - - - diff --git a/docs/reference/gtk/tmpl/gtkrc.sgml b/docs/reference/gtk/tmpl/gtkrc.sgml index 178b403922..4c81682d17 100644 --- a/docs/reference/gtk/tmpl/gtkrc.sgml +++ b/docs/reference/gtk/tmpl/gtkrc.sgml @@ -496,6 +496,7 @@ This can later be composited together with other #GtkRcStyle structures to form a #GtkStyle. +@parent_instance: @name: @bg_pixmap_name: @font_desc: diff --git a/docs/reference/gtk/tmpl/gtktextview.sgml b/docs/reference/gtk/tmpl/gtktextview.sgml index f168889dc6..e4b5b21462 100644 --- a/docs/reference/gtk/tmpl/gtktextview.sgml +++ b/docs/reference/gtk/tmpl/gtktextview.sgml @@ -660,6 +660,16 @@ types related to the text widget and how they work together. + + + + + + + + + + diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index a3ebb8f284..59eb2f3502 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,8 @@ +2001-04-18 Havoc Pennington + + * gdk-pixbuf.c (gdk_pixbuf_fill): Function to fill pixbuf with a + given color. + Wed Apr 4 01:41:02 2001 Tim Janik * pixops/Makefile.am (noinst_LTLIBRARIES): include $top_srcdir diff --git a/gdk-pixbuf/gdk-pixbuf.c b/gdk-pixbuf/gdk-pixbuf.c index 2a65082d93..12b8e61441 100644 --- a/gdk-pixbuf/gdk-pixbuf.c +++ b/gdk-pixbuf/gdk-pixbuf.c @@ -409,6 +409,64 @@ gdk_pixbuf_error_quark (void) return q; } +/** + * gdk_pixbuf_fill: + * @pixbuf: a #GdkPixbuf + * @pixel: RGBA pixel to clear to (0xffffff00 is opaque white, 0x000000ff transparent black) + * + * Clears a pixbuf to the given RGBA value, converting the RGBA value into + * the pixbuf's pixel format. The alpha will be ignored if the pixbuf + * doesn't have an alpha channel. + * + **/ +void +gdk_pixbuf_fill (GdkPixbuf *pixbuf, + guint32 pixel) +{ + guchar *pixels; + gboolean all_the_same = FALSE; + guint r, g, b, a; + + g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); + + pixels = pixbuf->pixels; + + r = (pixel & 0xff000000) >> 24; + g = (pixel & 0x00ff0000) >> 16; + b = (pixel & 0x0000ff00) >> 8; + a = (pixel & 0x000000ff); + + if (r == g && g == b) { + if (!pixbuf->has_alpha) + all_the_same = TRUE; + else + all_the_same = (r == a); + } + + if (all_the_same) { + memset (pixels, r, + pixbuf->rowstride * pixbuf->height); + } else { + guchar *p; + guchar *end; + + /* feel free to optimize this */ + + p = pixels; + end = pixels + pixbuf->rowstride * pixbuf->height; + end -= (pixbuf->rowstride - pixbuf->width); + + while (p < end) { + *p++ = r; + *p++ = g; + *p++ = b; + if (pixbuf->has_alpha) + *p++ = a; + } + } +} + + /* Include the marshallers */ #include #include "gdk-pixbuf-marshal.c" diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index dd40abbe43..b8b5a03af0 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -145,6 +145,9 @@ GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf, int length, GError **error); +/* Mutations */ +void gdk_pixbuf_fill (GdkPixbuf *pixbuf, + guint32 pixel); /* Saving */ diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 48da4edcd0..03f5fe0b68 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -934,12 +934,8 @@ static void gtk_image_reset (GtkImage *image) { gtk_image_clear (image); - - GTK_WIDGET (image)->requisition.width = 0; - GTK_WIDGET (image)->requisition.height = 0; - - if (GTK_WIDGET_VISIBLE (image)) - gtk_widget_queue_resize (GTK_WIDGET (image)); + + gtk_image_update_size (image, 0, 0); } static void @@ -951,6 +947,12 @@ gtk_image_size_request (GtkWidget *widget, image = GTK_IMAGE (widget); + /* We update stock/icon set on every size request, because + * the theme could have affected the size; for other kinds of + * image, we just update the requisition when the image data + * is set. + */ + switch (image->storage_type) { case GTK_IMAGE_STOCK: @@ -976,9 +978,9 @@ gtk_image_size_request (GtkWidget *widget, if (pixbuf) { - gtk_image_update_size (image, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); + GTK_WIDGET (image)->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2; + GTK_WIDGET (image)->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2; + g_object_unref (G_OBJECT (pixbuf)); } @@ -993,6 +995,9 @@ gtk_image_update_size (GtkImage *image, { GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2; GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2; + + if (GTK_WIDGET_VISIBLE (image)) + gtk_widget_queue_resize (GTK_WIDGET (image)); } diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index d9de973429..3f9f6bdb20 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4970,6 +4970,8 @@ gtk_text_view_do_popup (GtkTextView *text_view, GtkWidget *menuitem; GtkWidget *submenu; gboolean have_selection; + gboolean can_insert; + GtkTextIter iter; if (text_view->popup_menu) gtk_widget_destroy (text_view->popup_menu); @@ -4982,13 +4984,20 @@ gtk_text_view_do_popup (GtkTextView *text_view, have_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view), NULL, NULL); + + gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), + &iter, + gtk_text_buffer_get_insert (get_buffer (text_view))); + + can_insert = gtk_text_iter_editable (&iter, text_view->editable); append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard", have_selection); append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard", have_selection); + append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard", - TRUE); + can_insert); menuitem = gtk_separator_menu_item_new (); gtk_widget_show (menuitem); -- 2.30.2